package com.yzh.luckydraw.domain.strategy.service.algorithm;

import com.yzh.luckydraw.domain.strategy.model.vo.AwardRateInfo;

import java.util.List;

public interface IDrawAlgorithm {
    /**
     * 程序启动时初始化概率元祖，在初始化完成后使用过程中不允许修改元祖数据
     * 元祖数据作用在于百分比内（0.2、0.3、0.5）的数据，转换为一整条数组上分区的数据，如下：
     * 0.2 =             0 ~ 0.2
     * 0.3 =       0 + 0.2 ~ 0.2 + 0.3
     * 0.5 = 0 + 0.2 + 0.3 ~ 0.2 + 0.3 + 0.5
     * 将数据概率分段后，再根据0-100中各个区间的奖品信息，使用斐波那契散列计算出索引位置，把奖品数据存入元祖中，比如：
     * 1. 把0.2(概率)转为20
     * 2. 20对应的斐波那契哈希值：(20 * 散列增量 + 散列增量) = -1549107828，增量为：0x61c88647
     * 3. 再通过哈希值计算索引位置：hashCode & (rateTuple.length - 1) = 12
     * 4. 那么tup[12] = 0.2概率对应的奖品
     * 5. 当后续经过随机数获得1-100的值后，可以直接定位对应的奖品信息，通过这样的方式把循环匹配范围值的时间复杂度降至O(1)
     *
     * @param strategyId        策略ID
     * @param strategyMode      策略类型（总体概率、单项概率）
     * @param awardRateInfoList 奖品概率配置集合，例如[AwardRateInfo.awardRate = 0.04]
     */
    void initRateTuple(Long strategyId, Integer strategyMode, List<AwardRateInfo> awardRateInfoList);

    /**
     * 判断是否已经做了初始化数据
     *
     * @param strategyId
     * @return
     */
    boolean isExist(Long strategyId);

    /**
     * 生成随机数，索引到对应的奖品信息返回结果
     *
     * @param strategyId      策略ID
     * @param excludeAwardIds 排除掉已经不能作为抽奖的奖品ID
     * @return
     */
    String randomDraw(Long strategyId, List<String> excludeAwardIds);
}
